package com.yunji.framework_template.common.util;

import java.io.UnsupportedEncodingException;
import java.lang.Character.UnicodeBlock;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;
import org.htmlparser.util.ParserException;

import com.yunji.framework_template.common.constant.Constant;

public class StringUtil {

    private static final Logger  log4j                   = Logger.getLogger(StringUtil.class);
    private static final Pattern specailCharacterPattern = Pattern.compile("\t|\r|\n");

    /**
     * 返回字符串的值，如果字符串为空则返回默认值
     * 
     * @param src 字符串
     * @param defaultValue 默认值
     * @return
     */
    public static final String nvl(String src, String defaultValue) {
        if (src != null && src.length() > 0) {
            return src;
        } else {
            return defaultValue;
        }
    }

    public static final String nvl(String src) {
        return nvl(src, "");
    }

    /**
     * 得到当前日期/时间字符串
     * 
     * @return 返回日期/时间字符串
     */
    public static String getNowDateTimeString(String type) {
        Date date = new Date();
        SimpleDateFormat formattxt = new SimpleDateFormat(type);
        return formattxt.format(date);
    }

    /**
     * 判断给入的字符串是否为空,null、""、" "都表示空字符串
     * 
     * @param str 待判定的字符串
     * @return 空符串返回true，否则返回false
     */
    public static boolean isEmpty(String str) {
        if (null == str || str.trim().length() == 0) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    public static String blankString(int num) {
        String str = Constant.EMPTY_STRING;
        while (num > 0) {
            str += Constant.BLANK_STRING;
            num--;
        }
        return str;
    }

    /**
     * 字符串截取
     * 
     * @param childContent
     * @param startList
     * @param endList
     * @return
     * @throws RuntimeException
     * @throws ParserException
     */
    public static String subString(String childContent, List<String> startList, List<String> endList) {
        int startSize = startList.size();
        for (int i = 0; i < startSize; i++) {
            try {
                childContent = StringUtil.subString(childContent, startList.get(i), endList.get(i));
                break;
            } catch (Exception e) {
                if (i + 1 == startSize) {
                    throw new RuntimeException(e);
                } else {
                    log4j.debug("第 " + (i + 1) + " 次获取文章内容出错！");
                }
            }
        }
        return childContent;
    }

    /**
     * 从原始字符串中，取得从start字符串开始但不包括start字符串，到end字符串为止其中所有的字符，如str='aabbccddee',start='bb',end='ee',则此时结果为'ccdd'。
     * 开始及结束字符串必须存在，否则就报错。
     * 
     * @param src 源字符串
     * @param start 开始字符串
     * @param end 结尾字符串
     * @return 开始字符串到结尾字符串的中间字符串
     * @throws Exception
     */
    public static String subString(String src, String start, String end) {
        int startIndex = src.indexOf(start);
        int endIndex = src.indexOf(end);
        if (src == null || start == null || end == null || startIndex < 0 || endIndex < 0) {
            return null;
        }
        if (start != null && startIndex >= 0) {
            src = src.substring(startIndex).substring(start.length());
        }
        endIndex = src.indexOf(end);
        if (end != null && endIndex >= 0) {
            src = src.substring(0, endIndex);
        }
        return src;
    }

    /**
     * 字符串截取，与subString不同的是，开始字符串lastStart不是从字符串开始查找到的第一个，而是找到的最后一个lastStart字符串，然后再截取到从这个时候开始的end字符串为止，如下示例：<br>
     * 如有一个字符串是：aa1111bb222aa3333bb4444bb，传入的参数lastStart为aa，end为bb，则时得到的结果为:<br>
     * <b>3333</b>
     * 
     * @param src 源字符串
     * @param start 当前字符串中的最后一个开始字符串
     * @param end 结尾字符串
     * @return
     */
    public static String subStringFromLastStart(String src, String lastStart, String end) {
        int startIndex = src.lastIndexOf(lastStart);
        int endIndex = src.lastIndexOf(end);
        if (!(startIndex > 0 && endIndex > 0 && endIndex > startIndex)) {
            return null;
        }
        src = src.substring(startIndex + lastStart.length());
        src = src.substring(0, src.indexOf(end));
        return src;
    }

    /**
     * 从原始字符串中，取得从start字符串开始但不包括start字符串，到end字符串为止其中所有的字符，如str='aabbccddee',start='bb',end='ee',则此时结果为'ccdd'。
     * 如果开始字符串不存在，则开始处为原字符串的第一字符，如果结束字符串不存在，则为字符串的最后一个字符。果
     * 
     * @param src 源字符串
     * @param start 开始字符串
     * @param end 结尾字符串
     * @return 开始字符串到结尾字符串的中间字符串
     * @throws Exception
     */
    public static String subStringSmart(String src, String start, String end) {
        if (!isEmpty(start)) {
            src = src.indexOf(start) > -1 ? src.substring(src.indexOf(start)).substring(start.length()) : src;
        }
        if (!isEmpty(end)) {
            src = src.indexOf(end) > -1 ? src.substring(0, src.indexOf(end)) : src;
        }
        return src;
    }

    /**
     * 根据传入的内容，去掉所有html标签，目前此方法的实现来源于这里：http://www.rgagnon.com/javadetails/java-0424.html
     * 
     * @param htmlSource
     * @return
     */
    public static String removeHtmlTags(String htmlSource) {
        return htmlSource.replaceAll("\\<.*?>", "");
    }

    // /**
    // * 去掉script
    // *
    // * @param htmlSource
    // * @return
    // */
    // public static String removeScript(String htmlSource) {
    // htmlSource = htmlSource.replaceAll("<script.*</script>", "");
    // return htmlSource;
    // }

    /**
     * 去掉script及其中的内容
     * 
     * @param htmlSource
     * @return
     */
    public static String removeScriptByLoopFind(String htmlSource) {
        htmlSource = htmlSource.replaceAll("<script.*</script>", "");
        int start = -1;
        int end = -1;
        String temp = null;
        String endScript = "</script>";
        while ((start = htmlSource.indexOf("<script")) >= 0) {
            end = htmlSource.indexOf(endScript);
            if (end < 0) {
                break;
            }
            if (start < end) {
                temp = htmlSource.substring(start, end + endScript.length());
                htmlSource = htmlSource.replace(temp, "");
            } else if (start >= end) {
                break;
            }
        }
        return htmlSource;
    }

    /**
     * 去掉script及其中的内容
     * 
     * @param htmlSource
     * @return
     */
    public static String removeScript(String htmlSource) {
        if(isEmpty(htmlSource)) {
            return htmlSource;
        }
        htmlSource = htmlSource.replaceAll("<script([\\s\\S]*?)</script>", "");
        return htmlSource;
    }

    /**
     * 去除超链接
     * 
     * @param htmlSource
     * @return
     */
    public static String removeHreflink(String htmlSource) {
        if(isEmpty(htmlSource)) {
            return htmlSource;
        }
        htmlSource = htmlSource.replaceAll("\\<a[^>]*>", "");
        htmlSource = htmlSource.replaceAll("\\</a>", "");
        return htmlSource;
    }
    /**
     * 从给定的内容中删除超链接以及超链接中的内容
     * @param htmlSource
     * @return
     */
    public static String removeHreflinkAndContent(String htmlSource) {
        if(isEmpty(htmlSource)) {
            return htmlSource;
        }
        htmlSource = htmlSource.replaceAll("<a[^>]*>([\\s\\S]*?)</a>", "");
        return htmlSource;
    }

    /**
     * 删除script标签及超链接
     * 
     * @param htmlSource
     * @return
     */
    public static String removeScriptAndHrefTags(String htmlSource) {
        htmlSource = removeScript(htmlSource);
        htmlSource = removeHreflink(htmlSource);
        return htmlSource;
    }

    /**
     * 在“源字符串”中“被查找的字串”之前，在“被查找的字符串”之前补充“增加的字符串”。<br>
     * 注：该方法存在BUG，不支持多个被查找字符串连在一起。
     * 
     * @param source 源字符串
     * @param locateString 被查找的字符串
     * @param addString 增加的字符串
     * @return
     */
    public static String addStringBeforeAll(String source, String locateString, String addString) {
        int index = 0;
        StringBuffer realBody = new StringBuffer(source);
        String bstr = StringUtil.blankString(addString.length() + locateString.length());
        while ((index = source.indexOf(locateString)) >= 0) {
            source = bstr + source.substring(0, index - 1) + source.substring(index + locateString.length() - 1);
            realBody = realBody.insert(index, addString);
        }
        return realBody.toString();
    }

    /**
     * 根据指定的分隔符，从源字符串查找到最后一个分隔符，然后返回此分隔符前面的内容，如果找不到此分隔符则返回原字符串，
     * 
     * @param str
     * @param separator
     * @return
     */
    public static String substringBeforeLast(String str, String separator) {
        if ((str == null) || (separator == null) || (str.length() == 0) || (separator.length() == 0)) {
            return str;
        }

        int pos = str.lastIndexOf(separator);

        if (pos == -1) {
            return str;
        }

        return str.substring(0, pos);
    }

    /**
     * 根据指定的分隔符，从源字符串查找到最后一个分隔符，然后返回此分隔符前面的内容，如果找不到此分隔符则返回原字符串。<br>
     * 此时会把分隔符加到分隔后得到的字符串再返回，前提是找到了此分隔符，否则返回原字符串，不加上分隔符
     * 
     * @param str
     * @param separator
     * @return
     */
    public static String substringBeforeLastWithSeparator(String str, String separator) {
        String result = substringBeforeLast(str, separator);
        if (!result.equals(str)) {
            result += separator;
        }
        return result;
    }

    /**
     * 如果传入的值为null，则返回""，否则返回原值
     * 
     * @param str
     * @return
     */
    public static String returnBlankIfNull(String str) {
        return str == null ? "" : str;
    }

    /**
     * 如果传入的值为null，则返回false，否则返回相应的boolean值
     * 
     * @param str
     * @return
     */
    public static Boolean returnFalseIfNull(String str) {
        return str == null ? Boolean.FALSE : Boolean.parseBoolean(str);
    }

    /**
     * 从给定的内容content中获取给定的start字符串到end字符串的所有内容，其中start和end的配对可以是多处，最终以List结果返回。<br>
     * 如给定的内容content为：adfadfsdfasBBttttCCxaafdsfdsBBddadfasfsfdCCxxxx，<br>
     * start为:BB<br>
     * end为：CC<br>
     * 则返回的list结果包括两条记录：tttt 和 ddadfasfsfd.<br>
     * 在获取时，end字符串所处的位置一定要大于start所处的位置，否则不以处理，默认来配对不成功，跳出处理的循环。
     * 
     * @param content 待获取回复的内容
     * @param start 一个回复的开始分隔字符串
     * @param end 一个回复的结束分隔字符串
     * @param isFirstMainContent 第一项是否主内容，如论坛的内容和回复的分隔符都是一样的，此时在这个址为true的情况下，第一项不做为后回复，后面的才做为回复
     * @return
     */
    public static List<String> getListFromStart2End(String content, String start, String end,
                                                    boolean isFirstMainContent) {
        List<String> replysList = new ArrayList<String>();
        if (content.indexOf(start) < 0) {
            return replysList;
        }
        int index_start = -1;
        int num = 1;
        while ((index_start = content.indexOf(start)) >= 0) {
            content = content.substring(index_start);
            int index_end = content.indexOf(end);
            if (index_end > 0) {
                String reply = StringUtil.subString(content, start, end);
                if (!isFirstMainContent || (isFirstMainContent && num > 1)) {
                    replysList.add(reply);
                }
                content = content.substring(content.indexOf(end) + end.length());
            } else {
                break;
            }
            num++;
        }
        return replysList;
    }

    /**
     * 内容替换
     * 
     * @param content
     * @param from
     * @param to
     * @return
     */
    public static String replaceContent(String content, String from, String to) {
        return replaceContent(content, from, to, Boolean.FALSE);
    }

    /**
     * 对文章内容进行特殊处理，如文章内容替换，或者也通过实现的HANDLER处理，Handler需要实现接口{@link it.renren.spilder.task.handler.Handler Handler}
     * 
     * @param content
     * @param from
     * @param to
     * @param isIssRegularExpression
     * @return
     */
    public static String replaceContent(String content, String from, String to, boolean isIssRegularExpression) {
        List<String> fromList = new ArrayList<String>();
        List<String> toList = new ArrayList<String>();
        fromList.add(from);
        toList.add(to);
        return replaceContent(content, fromList, toList, isIssRegularExpression);
    }

    /**
     * 内容替换，根据列表的内容进行进行替换，替换字符列表与被替换字符串列表的数量要相同
     * 
     * @param content
     * @param fromList
     * @param toList
     * @return
     */
    public static String replaceContent(String content, List<String> fromList, List<String> toList) {
        return replaceContent(content, fromList, toList, Boolean.FALSE);
    }

    /**
     * 内容替换，根据列表的内容进行进行替换，替换字符列表与被替换字符串列表的数量要相同。可根据指定的参数进行是否正则替换
     * 
     * @param content
     * @param fromList
     * @param toList
     * @param isIssRegularExpression
     * @return
     */
    public static String replaceContent(String content, List<String> fromList, List<String> toList,
                                        boolean isIssRegularExpression) {
        if (fromList == null || fromList.size() == 0 || toList == null || toList.size() == 0) {
            return content;
        }
        if (fromList.size() != toList.size()) {
            throw new RuntimeException("The sourceList size must be the same as the descList.");
        }
        int index = 0;
        for (String from : fromList) {
            String to = toList.get(index);
            index++;
            if (from == null || "".equals(from) || to == null || "".equals(to)) {
                continue;
            }
            if (content.indexOf(from) >= 0) {
                if (!StringUtil.isEmpty(from) && !StringUtil.isEmpty(to)) {
                    if (isIssRegularExpression) {
                        content = content.replaceAll(from, to);
                    } else {
                        content = content.replace(from, to);
                    }
                }
            }
        }

        return content;
    }

    /**
     * 检查被检查的字符串(find)在原字符串(source)中是不是只出现了一次
     * 
     * @param source 原字符串
     * @param find 被检查的字符串
     * @return
     */
    public static boolean checkExistOnlyOnce(String source, String find) {
        if (StringUtil.isEmpty(source) || StringUtil.isEmpty(find)) {
            return false;
        }
        int indexOf = source.indexOf(find);
        if (indexOf < 0) {
            return false;
        }
        int lastIndexOf = source.lastIndexOf(find);
        if (lastIndexOf < 0) {
            return false;
        }
        if (indexOf == lastIndexOf) {
            return true;
        }
        return false;
    }

    /**
     * 字符编码转换
     * 
     * @param source
     * @param srcEncode
     * @param destEncode
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String ConverterStringCode(String source, String srcEncode,
                                             String destEncode) throws UnsupportedEncodingException {
        return new String(source.getBytes(srcEncode), destEncode);

    }

    /**
     * 去除给定的字符串中，所有非字母、数字、空格的字符
     * 
     * @param str
     * @return
     */
    public static String removeNonLetterAndNumberCharacter(String str) {
        if (isEmpty(str)) {
            return str;
        }
        str = str.trim();
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < str.length(); i++) {
            char cha = str.charAt(i);
            if ((cha >= 48 && cha <= 57) || (cha >= 65 && cha <= 90) || (cha >= 97 && cha <= 122) || cha == 32) {
                result.append(cha);
            }
        }
        return result.toString();
    }

    /**
     * 去除给定的字符串中，所有非字母、数字、空格、逗号的字符
     * 
     * @param str
     * @return
     */
    public static String removeNonLetterAndNumberAndCommaCharacter(String str) {
        if (isEmpty(str)) {
            return str;
        }
        str = str.trim();
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < str.length(); i++) {
            char cha = str.charAt(i);
            if (cha == 44 || (cha >= 48 && cha <= 57) || (cha >= 65 && cha <= 90) || (cha >= 97 && cha <= 122)
                || cha == 32) {
                result.append(cha);
            }
        }
        return result.toString();
    }

    /**
     * 将传入的内容，根据分隔符进行拆分，并将拆分后的结果以List的方式返回
     * 
     * @param content 待待分的内容
     * @param splitChar 内容分隔符
     * @return
     */
    public static List<String> getContentList(String content, String splitChar) {
        List<String> list = new ArrayList<String>();
        if (isEmpty(content)) {
            return list;
        }
        // 将Windows的回车换行符，替换为换行符
        content = content.replace("\r\n", "\n");

        int end = -1;
        String temp = null;

        while ((end = content.indexOf(splitChar)) > 0) {
            temp = content.substring(0, end);
            list.add(temp);
            if (end + 1 < content.length()) {
                content = content.substring(end + 1, content.length());
            } else {
                break;
            }
        }
        if (!StringUtil.isEmpty(content)) {
            list.add(content);
        }
        return list;
    }

    /**
     * 将给定的字符串，非数字以及字母的字符，全部替换为指定的字符
     * 
     * @param str
     * @param replaced
     * @return
     */
    public static String replaceNonCharAndNumer(String str, String replaced) {
        if (isEmpty(str)) {
            return str;
        }
        str = str.trim();
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            if ((ch >= 48 && ch <= 57) || (ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122)) {
                result.append(ch);
            } else {
                result.append(replaced);
            }
        }
        return result.toString();
    }

    /**
     * 检查给定的字符串是否只有字符、数字以及下画线
     * 
     * @param str
     * @return
     */
    public static boolean checkIfOnlyIncludeCharacterNumberUnderline(String str) {
        if (isEmpty(str)) {
            return false;
        }
        str = str.trim();
        for (int i = 0; i < str.length(); i++) {
            char cha = str.charAt(i);
            if (!((cha >= 48 && cha <= 57) || (cha >= 65 && cha <= 90) || (cha >= 97 && cha <= 122) || cha == 95)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 四舍五入并去掉科学计数法, 默认小数点2位.
     * 
     * @param value String, double, Double, BigDecimal
     * @return
     * @author fenglb
     * @date 2012-7-28 下午03:44:05
     */
    public static String toNuSicen(Object value) {
        return toNuSicen(value, 2);
    }

    /**
     * 四舍五入并去掉科学计数法.
     * 
     * @param value String, double, Double, BigDecimal
     * @param precision 保留几位小数
     * @return
     * @author fenglb
     * @date 2012-7-28 下午03:47:25
     */
    public static String toNuSicen(Object value, int precision) {
        Object result = "";
        DecimalFormat df = new DecimalFormat();
        df.setMinimumFractionDigits(precision);
        df.setMaximumFractionDigits(precision);
        df.setGroupingUsed(false);
        if (ObjectUtil.isEmpty(value)) {
            return df.format(0);
        } else if (value instanceof BigDecimal) {
            result = value;
        } else if (value instanceof String) {
            result = new BigDecimal(String.valueOf(value));
        } else if (value instanceof Number) {
            result = Double.parseDouble(value.toString());
        } else {
            throw new IllegalArgumentException(value + "need extends Number or String");
        }
        return df.format(result);
    }

    /**
     * 生成uuid
     * 
     * @return
     */
    public static String getUUID() {
        return UUID.randomUUID().toString();
    }

    /**
     * 去除除字母和空格之外的所有字符
     * 
     * @param str
     * @return
     */
    public static String removeNonStringAndNumber(String str) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < str.length(); i++) {
            char cha = str.charAt(i);
            if ((cha >= 48 && cha <= 57) || (cha >= 65 && cha <= 90) || (cha >= 97 && cha <= 122)) {
                sb.append(str.charAt(i));
            }
        }
        return sb.toString();
    }

    /**
     * 去除字符串中的空格、回车、换行符、制表符等
     * 
     * @param str
     * @return
     */
    public static String replaceSpecialStr(String str) {
        String repl = "";
        if (str != null) {
            Matcher m = specailCharacterPattern.matcher(str);
            repl = m.replaceAll("");
        }
        return repl;
    }

    /**
     * 判断字符是否是中文
     *
     * @param c 字符
     * @return 是否是中文
     */
    public static boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
            || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
            || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
            || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
            || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
            || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS || ub == Character.UnicodeBlock.TAMIL
            || ub == Character.UnicodeBlock.ARABIC) {
            return true;
        }
        return false;
    }

    /**
     * 判断字符串是否是乱码
     *
     * @param strName 字符串
     * @return 是否是乱码
     */
    public static boolean isMessyCode(String strName) {
        if(StringUtil.isEmpty(strName)) {
            return false;
        }
        Pattern p = Pattern.compile("\\s*|t*|r*|n*");
        Matcher m = p.matcher(strName);
        String after = m.replaceAll("");
        String temp = after.replaceAll("\\p{P}", "");
        char[] ch = temp.trim().toCharArray();
        float chLength = ch.length;
        float count = 0;
        for (int i = 0; i < ch.length; i++) {
            char c = ch[i];
            Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
            if (ub == UnicodeBlock.LATIN_1_SUPPLEMENT) {// LATIN_1_SUPPLEMENT可以理解为通常说的乱码
                count++;
            }
        }
        float result = count / chLength;
        if (result > 0.3) {
            return true;
        } else {
            return false;
        }

    }
}
